package com.quectel.cms.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.quectel.util.common.JacksonUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 区域帮助类
 */
public class RegionUtils {

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static final class ReignStruct {
        private String code;
        private String name;
        /**
         * 没有为null
         */
        private String parentCode;
        /**
         * 没有为null
         */
        private String parentName;
        /**
         * 1省2市3区4街道
         */
        private Byte level;

    }

    /**
     * 根据code查询详细信息
     *
     * @param code
     * @return
     */
    public static ReignStruct getByCode(String code) {
        if (StringUtils.isBlank(code)) {
            return null;
        }
        return CACHE.get(code);
    }

    /**
     * 根据codes查询列表
     *
     * @param codes
     * @return
     */
    public static List<ReignStruct> getByCodes(Set<String> codes) {
        return CACHE.values().stream().filter((o) -> codes.contains(o.getCode())).collect(Collectors.toList());
    }

    /**
     * 根据codes查询列表
     *
     * @param code
     * @return
     */
    public static List<ReignStruct> getByParentCode(String code) {
        return CACHE.values().stream().filter((o) -> Objects.equals(code, o.getParentCode())).collect(Collectors.toList());
    }

    /**
     * 查询省市区街道信息
     *
     * @param level 1省2市3区4街道
     * @param name  模糊匹配 为null标识不按照名称
     * @return
     */
    public static List<ReignStruct> getByLevelAndName(Byte level, String name) {
        return CACHE.values().stream().filter((o) ->
                {
                    if (!o.getLevel().equals(level)) {
                        return false;
                    }
                    if (StringUtils.isNotBlank(name)) {
                        if (!o.getName().contains(name)) {
                            return false;
                        }
                    }
                    return true;
                }

        ).collect(Collectors.toList());
    }

    /**
     * key区域code
     */
    private static final Map<String, ReignStruct> CACHE = new ConcurrentHashMap<>();

    static {
        synchronized (RegionUtils.class) {
            try (InputStream resourceAsStream =
                         RegionUtils.class.getClassLoader().getResourceAsStream("conf/region/pcas-code.json")) {
                String json = IOUtils.toString(resourceAsStream, "utf-8");
                JsonNode provinces = JacksonUtils.parse(json);
                for (int i = 0; i < provinces.size(); i++) {
                    JsonNode province = provinces.get(i);
                    CACHE.put(
                            province.get("code").asText(),
                            new ReignStruct(
                                    province.get("code").asText(),
                                    province.get("name").asText(),
                                    null,
                                    null,
                                    (byte) 1

                            )
                    );
                    JsonNode cities = province.findValue("children");
                    if (cities != null) {
                        for (int j = 0; j < cities.size(); j++) {
                            JsonNode city = cities.get(j);
                            CACHE.put(
                                    city.get("code").asText(),
                                    new ReignStruct(
                                            city.get("code").asText(),
                                            city.get("name").asText(),
                                            province.get("code").asText(),
                                            province.get("name").asText(),
                                            (byte) 2

                                    )
                            );
                            JsonNode counties = city.findValue("children");
                            if (counties != null) {
                                for (int k = 0; k < counties.size(); k++) {
                                    JsonNode county = counties.get(k);
                                    CACHE.put(
                                            county.get("code").asText(),
                                            new ReignStruct(
                                                    county.get("code").asText(),
                                                    county.get("name").asText(),
                                                    city.get("code").asText(),
                                                    city.get("name").asText(),
                                                    (byte) 3

                                            )
                                    );
                                    JsonNode streets = county.findValue("children");
                                    if (streets != null) {
                                        for (int m = 0; m < streets.size(); m++) {
                                            JsonNode street = streets.get(m);
                                            CACHE.put(
                                                    street.get("code").asText(),
                                                    new ReignStruct(
                                                            street.get("code").asText(),
                                                            street.get("name").asText(),
                                                            county.get("code").asText(),
                                                            county.get("name").asText(),
                                                            (byte) 4
                                                    )
                                            );
                                        }
                                    }
                                }
                            }
                        }
                    }


                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}
